//    Copyright (C) Kherty.  All rights reserved.
using System.Collections.Generic;
using OpenLS.Core.Serialization;
using OpenLS.Vml;
using OpenLS.Vml.Spreadsheet;

namespace OpenLS.Spreadsheet.Internals
{
    class InternalComments: IOfficeXmlSerializable
    {
        #region IOfficeXmlSerializable Members

        public void ReadXml(ReadContext context)
        {
            using (ReadContext c = context.Read("comments"))
            {
                using (ReadContext authorsC = c.Read("authors"))
                {
                    while (authorsC.ReaderLocalName == "author")
                        Authors.Add(authorsC.ReadElementString("author"));
                }
                using (ReadContext commentListC = c.Read("commentList"))
                {
                    while (commentListC.ReaderLocalName == "comment")
                    {
                        Comments.Add(commentListC.ReadElement<CommentInternal>());
                    }
                }
                Extension = c.ReadOptionalElement<ExtensionElement>("extLst");
            }
            
        }

        public void WriteXml(WriteContext context)
        {
            using (WriteContext c = context.Write("comments"))
            {
                using (WriteContext authorsC = c.Write("authors"))
                {
                    foreach (string au in Authors)
                    {
                        using (var authorContext = authorsC.Write("author"))
                            authorContext.WritePreservedString(au);
                    }
                }
                using (WriteContext commentListC = c.Write("commentList"))
                {
                    foreach (CommentInternal ci in Comments)
                        commentListC.WriteElement(ci);
                }
                c.WriteOptionalElement(Extension);
            }
        }

        internal void ApplyTo(Worksheet worksheet)
        {
            Dictionary<CellAddress, Shape> shapes = new Dictionary<CellAddress, Shape>();
            foreach (Shape shape in Enumerable.OfType<Shape>(worksheet.LegacyVmlDrawing.Items))
            {
                ClientData data = shape.GetElement<ClientData>();
                if (data == null)
                    continue;
                if (data.Row == null || data.Column == null)
                    continue;
                shapes.Add(new CellAddress(data.Row.Value, data.Column.Value), shape);
            }
            foreach (CommentInternal c in Comments)
            {
                Cell cell = worksheet[c.Ref];
                Shape shape;
                shapes.TryGetValue(cell.Address, out shape);
                Comment comment = new Comment(cell, shape, Authors[c.AuthorId], c.Text);
                cell.Comment = comment;
            }
        }

        #endregion

        private ExtensionElement _extLst;

        public ExtensionElement Extension
        {
            get { return _extLst; }
            set { _extLst = value; }
        }
	
        private readonly List<string> _authors = new List<string>();

        public List<string> Authors
        {
            get { return _authors; }
        }
        private readonly List<CommentInternal> _comments = new List<CommentInternal>();
        public List<CommentInternal> Comments
        {
            get { return _comments; }
        }



        internal bool BuildFrom(Worksheet worksheet)
        {
            Dictionary<string, int> authors = new Dictionary<string, int>();
            bool result = false;
            ShapeType type = null;
            foreach (Cell cell in worksheet.NonVolatileCells)
            {
                Comment comment = cell.Comment;
                if (comment == null)
                    continue;
                if (!comment.IsMeaningful)
                    continue;
                if (!result)
                {
                    type = new ShapeType();
                    type.CoordinateSize = "21600,21600";
                    type.Path = "m,l,21600r21600,l21600,xe";
                    Stroke stroke = new Stroke();
                    stroke.JoinStyle = StrokeJoinStyle.Miter;
                    type.Elements.Add(stroke);
                    Path path = new Path();
                    path.GradientShapeOk = true;
                    path.ConnectType = ConnectType.Rectangle;
                    type.Elements.Add(path);
                    
                    worksheet.LegacyVmlDrawing.ShapeTypes.Add(type);
                    result = true;
                }
                comment.AdjustShape(type);
                int authorId;
                if (!authors.TryGetValue(comment.Author, out authorId))
                {
                    authorId = authors.Count;
                    authors.Add(comment.Author, authorId);
                    Authors.Add(comment.Author);
                }
                CommentInternal c = new CommentInternal();
                c.AuthorId = authorId;
                c.Text = comment.Text;
                c.Ref = cell.Label;
                Comments.Add(c);
            }
            return result;
        }
    }
}
